`timescale 1ns / 1ps

// kyber512 Decompress, du = 10, dv = 4
// Decompress -- du = 10, transform 10bit to 12bit
// 			  -- dv =  4, transform  4bit to 12bit

`define	KYBER_Q	12'd3329
`define	k_width 12

`define	du10	10
`define	dv4		4

`define	du11	11
`define	dv5		5

`define coeff_num 1 // coefficient number

module Kyber_Decompress(

	input 	d_mode, // d_mode, 0 = du, 1 = dv
	input 	k_mode, // k_mode, 0 = kyber512/768, 1 = kyber1024
					// for d_mode and k_mode select, the state is below 
					//		  0	        0            du10,	du=10 kyber512/768
					//		  1	        0            dv4,	dv=4  kyber512/768
					//		  0	        1            du11,	du=11 kyber1024
					//		  1	        1            dv5,	dv=5  kyber1024
	output 	[22*`coeff_num-1:0]	Mul_A,
	output 	[12*`coeff_num-1:0]	Mul_B,
	input 	[34*`coeff_num-1:0]	Mul_P,

	input 	[`k_width*`coeff_num - 1 : 0] data_in,
	output 	[`k_width*`coeff_num - 1 : 0] data_out

    );
	
//r->vec[i].coeffs[4*j+k] = ((uint32_t)(t[k] & 0x3FF)*KYBER_Q + 512) >> 10;
//r->coeffs[8*i+j] = ((uint32_t)(t[j] & 31)*KYBER_Q + 16) >> 5;
//r->coeffs[2*i+0] = (((uint16_t)(a[0] & 15)*KYBER_Q) + 8) >> 4;

wire	[`k_width - 1 + 1 : 0]	do_du10_temp;
wire	[`k_width - 1 + 1 : 0]	do_dv4_temp;
wire	[`k_width - 1 + 1 : 0]	do_du11_temp;
wire	[`k_width - 1 + 1 : 0]	do_dv5_temp;

reg 	[`k_width*`coeff_num - 1 : 0] data_out_temp;


assign Mul_A = 	data_in;
assign Mul_B = `KYBER_Q;

assign do_du10_temp = Mul_P[21:9]+1'b1;
assign do_dv4_temp  = Mul_P[15:3]+1'b1;
assign do_du11_temp = Mul_P[22:10]+1'b1;
assign do_dv5_temp  = Mul_P[16:4]+1'b1;

always@(*)
begin 
	case ({d_mode,k_mode})
		2'b00:	data_out_temp = do_du10_temp[12:1];	// du=10
		2'b10:	data_out_temp = do_dv4_temp[12:1];		// dv=4
		2'b01:  data_out_temp = do_du11_temp[12:1];	// du=11
		2'b11:  data_out_temp = do_dv5_temp[12:1];		// dv=5
	endcase
end

assign 	data_out = data_out_temp;


endmodule
